﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Security.Permissions;
using System.Drawing.Design;
using System.Web.UI.HtmlControls;

namespace jQuery.WebControls.UI
{
    

    /// <summary>
    /// Control web al estilo de MessageBox
    /// </summary>
    [AspNetHostingPermission(SecurityAction.Demand,
        Level = AspNetHostingPermissionLevel.Minimal),
    AspNetHostingPermission(SecurityAction.InheritanceDemand,
        Level = AspNetHostingPermissionLevel.Minimal), 
    DefaultProperty("Text")]
    [ToolboxData("<{0}:PopUp runat=server></{0}:PopUp>")]
    [Designer(typeof(PopUpDesigner)), Serializable()]
    public class PopUp : WebControl, IPostBackEventHandler
    {        
        /// <summary>
        /// Evento que se produce al hacer click sobre un botón del PopUp
        /// </summary>
        public event EventHandler Click;
        /// <summary>
        /// This event is thrown when the dialog is close. When Esc is pressed or one of the buttons
        /// which closes the dialog
        /// </summary>
        public event EventHandler CloseDialog;
        private bool mostrar;
        private bool respuesta;
        private string valor;        
        private jQueryScriptManager jQueryMngr;
        private bool vCloseOnEscape;

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            if (!Page.IsPostBack)
            {
                if(!DesignMode)
                    CheckQueryManager();
            }
        }

        /// <summary>
        /// Comprobación de los plugins y estilos necesarios para que funcione el PopUp
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
        }

        #region PROPIEDADES PUBLICAS
        /// <summary>
        /// Obtiene o establece si el PopUpPanel se puede redimensionar o no
        /// </summary>
        [Category("Appearance")]
        [DefaultValue(true)]
        [Description("Propiedad que indica si se muestra el botón en forma de X para cerrar el popup. Por defecto es true")]
        public bool ShowCloseButton
        {
            get
            {

                if (ViewState["vbc"] == null)
                {
                    ViewState.Add("vbc", true);
                }
                return bool.Parse(ViewState["vbc"].ToString());
            }
            set
            {
                ViewState["vbc"] = value;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        [Category("Appearance")]
        [DefaultValue("")]
        [Description("")]
        public string CommandName
        {
            get
            {
                if (ViewState["cmdName"] == null)
                {
                    ViewState.Add("cmdName", "");
                }
                return ViewState["cmdName"].ToString();
            }
            set
            {
                ViewState["cmdName"] = value;
            }
        }     
        /// <summary>
        /// 
        /// </summary>
        [Category("Appearance")]
        [DefaultValue("")]
        [Description("")]
        public string CommandArgument
        {
            get 
            {
                if (ViewState["cmdArgument"] == null)
                {
                    ViewState.Add("cmdArgument", "");
                }
                return ViewState["cmdArgument"].ToString();
            }
            set 
            {
                ViewState["cmdArgument"] = value;
            }
        }        

        /// <summary>
        /// Tipo de mensaje que se va a mostrar. Por defecto MessageType.Information
        /// </summary>
        [Category("Appearance")]
        [DefaultValue("MessageType.Information")]
        [Localizable(true)]
        [Description("Tipo de mensaje que se quiere mostrar")]
        public MessageType MessageType
        {
            get
            {                
                if (ViewState["MessageType"] == null)
                {
                    ViewState.Add("MessageType", MessageType.Information);
                }               
                return (MessageType)ViewState["MessageType"];
            }
            set
            {
                ViewState["MessageType"] = value;
            }
        }
               
        /// <summary>
        /// Texto del mensaje que se quiere mostrar en el pop-up 
        /// </summary>
        [Category("Appearance")]
        [DefaultValue("Texto")]
        [Localizable(true)]
        [Description("Texto del mensaje que se quiere mostrar en el pop-up")]
        public string Text
        {
            get
            {
                String s = (String)ViewState["Text"];
                return ((s == null) ? String.Empty : s);
            }
            set
            {
                ViewState["Text"] = value;
            }
        }

        /// <summary>
        /// Título del mensaje
        /// </summary>
        [Category("Appearance")]        
        [DefaultValue("Barra de MessageTitle")]
        [Localizable(true)]
        [Description("Título del mensaje")]
        public string MessageTitle
        {
            get
            {
                String s = (String)ViewState["MessageTitle"];
                return ((s == null) ? String.Empty : s);
            }
            set
            {
                ViewState["MessageTitle"] = value;
            }
        }

        /// <summary>
        /// Obtiene o establece si el PopUp se puede redimensionar o no
        /// </summary>
        [Category("Appearance")]
        [DefaultValue(true)]
        [Description("Propiedad que indica si se puede redimiensionar el pop-up. Por defecto es true")]
        public bool Resizable
        {
            get
            {

                if (ViewState["rdable"] == null)
                {
                    ViewState.Add("rdable", true);
                }
                return bool.Parse(ViewState["rdable"].ToString());
            }
            set
            {
                ViewState["rdable"] = value;
            }
        }

        /// <summary>
        /// Obtiene o establece texto del botón para indicar la acción de confirmar y aceptar. Por defecto, "Aceptar"
        /// </summary>
        [Category("Appearance")]
        [DefaultValue("Aceptar")]
        [Localizable(true)]
        [Description("Texto del botón para indicar la acción de confirmar y aceptar")]
        public string AcceptText
        {
            get
            {
                String s = (String)ViewState["txtOk"];
                return ((s == null) ? "Aceptar" : s);
            }
            set
            {
                ViewState["txtOk"] = value;
            }
        }

        /// <summary>
        /// Obtiene o establece texto del botón para indicar la acción de confirmar y aceptar. Por defecto, "Cancelar"
        /// </summary>
        [Category("Appearance")]
        [DefaultValue("Cancelar")]
        [Localizable(true)]
        [Description("Texto del botón para indicar la acción de cancelar o disconformidad con el mensaje que se muestra")]
        public string CancelText
        {
            get
            {
                String s = (String)ViewState["txtKO"];
                return ((s == null) ? "Cancelar" : s);
            }
            set
            {
                ViewState["txtKO"] = value;
            }
        }

        /// <summary>
        /// Obtiene o establece el ancho del PopUp. Por defecto, 500px
        /// </summary>
        [DefaultValue("500px")]
        [Category("Appearance")]
        [Description("Ancho del pop-up")]
        public override Unit Width
        {
            get { return (base.Width == null || base.Width.Value == 0 ? new Unit("500px") : base.Width); }
            set { base.Width = value;}
        }

        /// <summary>
        /// Propiedad que indica si se ha pulsado el botón aceptar o cancelar de un mensaje de tipo confirmación        
        /// </summary>
        public bool CallbackPrompt
        {
            get
            {              
                return respuesta;
            }           
        }

        /// <summary>
        /// Obtiene el texto introducido en el TextBox cuando el tipo de mensaje es MessageType.Prompt
        /// </summary>
        public string ValuePrompt { 
            get 
            {                
                return valor;                 
            } 
        }

        /// <summary>
        /// Gets or sets the X axe position where the dialog will be displayed
        /// </summary>
        [DefaultValue("PositionsX.Center")]
        [Category("Appearance")]
        [Description("Gets or sets the X axe position where the dialog will be displayed")]
        public PositionsX PositionX
        {
            get
            {
                if (ViewState["X"] != null)
                {
                    return (PositionsX)ViewState["X"];
                }
                else
                {
                    return PositionsX.Center;
                }                
            }
            set
            {
                ViewState["X"] = value;
            }
        }
        /// <summary>
        /// Gets or sets the Y axe position where the dialog will be displayed
        /// </summary>
        [DefaultValue("PositionsX.Center")]
        [Category("Appearance")]
        [Description("Gets or sets the Y axe position where the dialog will be displayed")]
        public PositionsY PositionY
        {
            get
            {
                if (ViewState["Y"] != null)
                {
                    return (PositionsY)ViewState["Y"];
                }
                else
                {
                    return PositionsY.Center;
                }                
            }
            set
            {
                ViewState["Y"] = value;
            }
        }
        [DefaultValue("PositionsX.Center")]
        [Category("Appearance")]
        [Description("Gets or sets if the dialog must be close when Escape is pressed")]
        public bool CloseOnEscape
        {
            get
            {
                return vCloseOnEscape;
            }
            set
            {
                vCloseOnEscape = value;
            }
        }
        #endregion

        #region PROPIEDADES PRIVADAS
        /// <summary>
        /// Ide de la capa para el pop-up
        /// </summary>
        private string IdSmartPopUpClient { get { return "m" + ClientID; } }

        /// <summary>
        /// Indica si se debe mostrar o no el popup
        /// </summary>
        private bool ShowPopUp
        {
            get
            {
                return mostrar;
            }
            set
            {
                mostrar = value;
            }
        }

        #endregion

        

        protected override void Render(HtmlTextWriter writer)
        {
            if (ShowPopUp)
            {
                writer.Write("<div id='" + IdSmartPopUpClient + "' title='" + MessageTitle + "' class='" + CssClass + "' style='" + getStyle() + "'>");
                writer.Write("<p>" + Text.Replace("\\n", "<br />").Replace("\r", "<br />"));                
                if (MessageType == MessageType.Prompt)
                {
                    writer.Write("<input type='text' id='txt" + IdSmartPopUpClient + "' name='txt" + IdSmartPopUpClient + "' style='width:95%' />");
                }
                writer.Write("<input type='hidden' id='hdd" + IdSmartPopUpClient + "' value='" + (CallbackPrompt ? "OK" : "KO") + "' /></p></div>");
            }
        }

        private string Script()
        {
            string getInputText = (MessageType == MessageType.Prompt ? "$('#txt" + IdSmartPopUpClient + "').val()" : "''");
            string eventoJscript;

            if (Click == null && MessageType == UI.MessageType.Confirm)
            {
                throw new ArgumentException(String.Format(Messages.PopUp_err1, ID));
            }
            else if (Click != null || CloseDialog != null)
            {
                eventoJscript = Page.ClientScript.GetPostBackEventReference(this, "sustituir");
            }
            else
            {
                eventoJscript = "";
            }

            string txtScript = "$('#" + IdSmartPopUpClient + "').dialog({";
            txtScript += "closeOnEscape: " + CloseOnEscape.ToString().ToLower() + ",";
            txtScript += "modal: " + (MessageType == MessageType.Confirm || MessageType == MessageType.Prompt ? "true," : "false,");
            txtScript += "resizable: " + (Resizable ? "true," : "false,");
            txtScript += getStyleDialog();
            if (!ShowCloseButton)
            {
                txtScript += " open: function(event, ui) { jQuery('.ui-dialog-titlebar-close').hide();},";
            }
            if (PositionX != PositionsX.Center || PositionY != PositionsY.Center)
            {
                txtScript += "position: ['" + PositionX.ToString().ToLower() + "','" + PositionY.ToString().ToLower() + "'],";
            }
            if (CloseDialog != null)
            {
                txtScript += "close: function(event, ui) { if(event.keyCode != null) if(event.keyCode == 27) {" +
                    "$('#hdd" + IdSmartPopUpClient + "').val('KO');" +
                    eventoJscript.Replace("'sustituir'", String.Format("'esc;{0};' + {1}", false, getInputText)) +
                    "}},";
            }
            txtScript += "buttons: {" +
                         "'" + AcceptText + "': function() { " +
                         "	$(this).dialog('close'); " +
                         "  $('#hdd" + IdSmartPopUpClient + "').val('OK');" +
                         "  " + eventoJscript.Replace("'sustituir'", String.Format("'btn;{0};' + {1}", true, getInputText)) +
                          "}";
            
            if (MessageType == MessageType.Confirm || MessageType == MessageType.Prompt)
            {
                txtScript += ", '" + CancelText + "': function() { " +
                 "	$(this).dialog('close'); " +
                 "  $('#hdd" + IdSmartPopUpClient + "').val('KO');" +
                 "  " + eventoJscript.Replace("'sustituir'", String.Format("'btn;{0};' + {1}", false, getInputText)) +
                 "} ";
            }
            txtScript += "}});";
            txtScript = "$(document).ready(function(){" + txtScript + "});";
            return txtScript;
        }
        
        #region SHOWING
        /// <summary>
        /// Abre el pop-up
        /// </summary>
        public void Show()
        {
            ClientScriptProxy.RegisterStartupScript(Page, GetType(), "showPop", Script(), true);
            ShowPopUp = true;
        }
        /// <summary>
        /// Abre el pop up
        /// </summary>
        /// <param name="MessageTitle">MessageTitle del mensaje</param>
        /// <param name="texto">Texto del mensaje</param>
        /// <param name="tipo">Tipo de mensaje</param>
        /// <param name="commandArgument"></param>
        public void Show(string MessageTitle, string texto, MessageType tipo, string commandArgument)
        {
            CommandArgument = commandArgument;
            Show(MessageTitle, texto, tipo);
        }

        /// <summary>
        /// Abre el pop up
        /// </summary>
        /// <param name="title">MessageTitle del mensaje</param>
        /// <param name="message">Texto del mensaje</param>
        /// <param name="mssgType">Tipo de mensaje</param>
        public void Show(string title, string message, MessageType mssgType)
        {
            MessageType = mssgType;
            MessageTitle = title;
            Text = message;
            Show();
        }

        /// <summary>
        /// Abre el pop up
        /// </summary>
        /// <param name="message">Texto del mensaje</param>
        /// <param name="mssgType">Tipo de mensaje</param>
        public void Show(string message, MessageType mssgType)
        {
            MessageType = mssgType;
            MessageTitle = mssgType.ToString();
            Text = message;
            Show();
        }
        /// <summary>
        /// Abre el pop-up como un mensaje pidiendo una confirmación
        /// </summary>
        /// <param name="title">MessageTitle del mensaje</param>
        /// <param name="message">Texto del mensaje</param>
        /// <param name="accept_text">Texto que aparecera en el botón para aceptar</param>
        /// <param name="cancel_text">Texto que aparecera en el botón para cancelar</param>
        public void Confirm(string title, string message, string accept_text, string cancel_text)
        {
            MessageType = MessageType.Confirm;
            MessageTitle = title;
            Text = message;
            AcceptText = accept_text;
            CancelText = cancel_text;
            Show();
        }
        #endregion

        /// <summary>
        /// Devuelve una cadena de HTML que contiene los estilos del control
        /// <example>
        ///     width: 200px; height: 100px; font-size: 10px
        /// </example>
        /// </summary>
        /// <returns></returns>
        private string getStyle()
        {
            string style = "";
            if (!Font.Size.IsEmpty)
                style += String.Format("font-size: {0};", Font.Size.ToString());
            if (Font.Bold.Equals(true))
                style += String.Format("font-weight: bold;");
            if (Font.Italic.Equals(true))
                style += String.Format("font-style: italic;");
            if (!ForeColor.IsEmpty)
                style += String.Format("color: {0};", System.Drawing.ColorTranslator.ToHtml(ForeColor));
            return style;
        }

        private string getStyleDialog()
        {
            string style = "";
            if (!Height.IsEmpty)
                style += String.Format("height: {0},", Height.Value.ToString());
            if (!Width.IsEmpty)
                style += String.Format("width: {0},", Width.Value.ToString());
           
            return (!String.IsNullOrEmpty(style) ? style : String.Empty);
        }
        
        #region Miembros de IPostBackEventHandler
        /// <summary>
        /// Evento que se lanza al hacer click en uno de los botones
        /// </summary>
        /// <param name="e"></param>
        protected virtual void OnClick(object sender, EventArgs e)
        {
            if (Click != null)
            {
                Click(sender, e);
            }
        }        

        void IPostBackEventHandler.RaisePostBackEvent(string eventArgument)
        {
            string auxCmdArgument = CommandArgument;
            string auxCmdName = CommandName;            
            string[] args = eventArgument.Split(Char.Parse(";"));
            bool isButtonSender = args[0].Equals("btn");

            respuesta = bool.Parse(args[1]);
            
            if (MessageType == MessageType.Prompt)
            {                
                if (respuesta)
                {
                    valor = eventArgument.Substring(eventArgument.LastIndexOf(';') + 1);
                }                
            }

            if (isButtonSender && Click != null)
                OnClick(this, new EventArgs());
            else if(!isButtonSender && CloseDialog != null)
                CloseDialog(this, new EventArgs());

            ResetCommandsAfterPostBackEvent(auxCmdArgument, auxCmdName);            
        }
        /// <summary>
        /// This procedure reset the CommandArgument and CommandName property if 
        /// the passed parameters are equals to this properties.
        /// </summary>
        /// <param name="cmdArgument">CommandArgument before raise Click event</param>
        /// <param name="cmdName">CommandName before raise Click event</param>
        private void ResetCommandsAfterPostBackEvent(string cmdArgument, string cmdName)
        {
            if (CommandArgument.Equals(cmdArgument))
            {
                CommandArgument = String.Empty;
            }
            if (CommandName.Equals(cmdName))
            {
                CommandName = String.Empty;
            }
        }
        #endregion       
    
        private ClientScriptProxy ClientScriptProxy
        {
            get
            {
                return ClientScriptProxy.Current;
            }
        }

        private jQueryScriptManager jQueryManager
        {
            get
            {
                if (jQueryMngr == null)
                    jQueryMngr = Common.Instance.Get_jQueryScriptManager(Page);
                return jQueryMngr;
            }
        }

        private void CheckQueryManager()
        {
            Common.Instance.CheckJQueryScriptManager(Page);
        }
    }
}
